package com.inibb.app.service.security.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.inibb.app.converter.AuthorityConverter;
import com.inibb.app.dao.JpaGenericDao;
import com.inibb.app.dao.api.IDao;
import com.inibb.app.po.security.Authority;
import com.inibb.app.po.security.Role;
import com.inibb.app.service.security.IAuthorityService;
import com.inibb.app.util.lang.StringUtil;
import com.inibb.app.vo.AuthoritySC;
import com.inibb.app.vo.ModuleDTO;
import com.inibb.app.vo.SubModuleDTO;
import com.inibb.app.vo.security.AuthorityDTO;


@Service
@Transactional
public class AuthorityServiceImpl implements IAuthorityService{
	
//	private HibernateDaoSupport authorityDao;
//	private SimpleHibernateTemplate<Role, Integer> roleDao;
	private IDao<Authority, Integer> authorityDao;
	private IDao<Role, Integer> roleDao;
	
	@PersistenceContext(unitName = "entityManager")
	private EntityManager entityManager ;
	
	@Autowired
	public void setEntityManagerFactory() {
		authorityDao = new JpaGenericDao<Authority, Integer>(entityManager, Authority.class);
		roleDao = new JpaGenericDao<Role, Integer>(entityManager, Role.class);
	}
	
	private AuthorityConverter converter = new AuthorityConverter();
	
	public Collection<AuthorityDTO> getAll() {
		return new AuthorityConverter().toDTOs(authorityDao.getAll());
//		List<Object[]> objs = authorityDao.queryNativeSqlForList("admin", "searchAuthorities", new PaginationCriteria(0,Integer.MAX_VALUE));
//		List<AuthorityDTO> gcList = new ArrayList<AuthorityDTO>();
//		for(Object[] obj:objs){
//			gcList.add(Db2VOConverter.toVO4Authorities(obj));
//		}
//		return gcList;
	}
	@SuppressWarnings("unchecked")
	private Collection<String> getSubModuleNames(final String modName) {
		Map<String, Object> criteria = new HashMap<String, Object>();
		criteria.put("modName", modName);
		return (Collection<String>) authorityDao.queryNativeSqlForList("admin", "searchSubModuleNameByModule", criteria);
		
//		DetachedCriteria criteria = DetachedCriteria.forClass(Authority.class);
//		criteria.add(Restrictions.eq("module", modName));
//		criteria.setProjection(Projections.distinct(Projections.property("subModule")));
//		return (Collection<String>) authorityDao.getHibernateTemplate().findByCriteria(criteria);
		
	}
	@SuppressWarnings("unchecked")
	private Collection<String> getAllModuleNames() {
		AuthoritySC sc = new AuthoritySC();
		sc.setStartRow(0);
		sc.setPageSize(Integer.MAX_VALUE);
		return (Collection<String>) authorityDao.queryNativeSqlForList("admin", "searchAllModuleName", sc);
		
//		DetachedCriteria criteria = DetachedCriteria.forClass(Authority.class);
//		criteria.setProjection(Projections.distinct(Projections.property("module")));
//		return (Collection<String>) authorityDao.getHibernateTemplate().findByCriteria(criteria);
	}
	
	public Collection<AuthorityDTO> getRoleAuthorities(final String roleId) {
		Role r = roleDao.get(Integer.parseInt(roleId));
		return converter.toDTOs(r.getAuths());
		
	}
	
	private Authority getAuthority(final Long authId) {
		return (Authority)authorityDao.get(authId.intValue());
	}
	
	
	public Collection<ModuleDTO> getAllModules() {
		return getAllModules(Collections.EMPTY_LIST);
	}

	
	public Collection<ModuleDTO> getAllModules(String roleId) {
		Collection<AuthorityDTO> roleAuthorities = getRoleAuthorities(roleId);
		return getAllModules(roleAuthorities);
		
	}
	
	public Collection<ModuleDTO> getAllModules(Collection<AuthorityDTO> grantedAuths) {
		Collection<AuthorityDTO> all = this.getAll();
		Collection<ModuleDTO> modules = new ArrayList<ModuleDTO>();
		for(String s:this.getAllModuleNames()){
			ModuleDTO mod = new ModuleDTO();
			mod.setName(s);
			modules.add(mod);
		}
		for(ModuleDTO mod: modules){
			for(String s:this.getSubModuleNames(mod.getName())){
				SubModuleDTO smod = new SubModuleDTO();
				smod.setName(s);
				
				for(AuthorityDTO auth:all){
					if(s.equals(auth.getSubModule())){
						auth.setGranted(auth.isGranted(grantedAuths));
						smod.addAuthority(auth);
					}
				}
				mod.addSubModule(smod);
			}
		}
		
		return modules;
		
	}
	
	public void save(final String[] authIds, final String roleId) {
		Role r = roleDao.get(Integer.parseInt(roleId));
		//Role r = (Role)session.get(Role.class, Long.valueOf(roleId));
		r.getAuths().clear();
		for(String id:authIds){
			id = StringUtil.trim(id);
			if(!StringUtil.isEmptyString(id)){

				Authority auth = authorityDao.get(Integer.parseInt(id));
				//(Authority)session.get(Authority.class, Long.valueOf(id));
				r.getAuths().add(auth);
			}
		}				
		roleDao.merge(r);		
		
	}
	
	
/*

	public void delete(AuthorityDTO authorityDTO) {
		authorityDao.delete( AuthorityConverter.toPO(authorityDTO) );
	}



	public Collection<AuthorityDTO> getAuthorityBy(PageFilter filter, PageSort sort) {
		HibernateFilter Hfilter = FilterUtils.toHibernateFilter(filter); 
	      HibernateSort Hsort = SortUtils.toHibernateSort(sort);
	      Criteria criteria = authorityDao.getSession().createCriteria( Authority.class );
	      criteria = Hfilter.execute(criteria);
	      criteria = Hsort.execute(criteria);
	      criteria.setFirstResult( filter.getRowStart() );
	      criteria.setMaxResults( filter.getRowEnd() - filter.getRowStart() );
	      
	      return (Collection<AuthorityDTO>)criteria.list();
	}

	public AuthorityDTO getAuthorityById(String id) {
		Long idLong=Long.parseLong(id);
		return AuthorityConverter.toDTO( 
				authorityDao.findUniqueByProperty("id", idLong) 
		);
	}

	public AuthorityDTO getAuthorityByName(String name) {
		return AuthorityConverter.toDTO( 
				authorityDao.findUniqueByProperty("name", name) 
		);
	}

	public int getAuthorityCountBy(PageFilter filter, PageSort sort) {
		HibernateFilter Hfilter = FilterUtils.toHibernateFilter(filter);
	      Criteria criteria = authorityDao.getSession().createCriteria( Authority.class );
	      criteria = Hfilter.execute(criteria);
	      criteria.setProjection(Projections.rowCount()).uniqueResult();
	      return ( (Integer)criteria.uniqueResult() ).intValue( );
	}



	public void update(AuthorityDTO authorityDTO) {
		authorityDao.save( AuthorityConverter.toPO(authorityDTO) );
	}
	*/


}
